Skip to content

CM-62578: Expose Cycode API v4 through CLI commands#435

Merged
MaorDavidzon merged 1 commit intomainfrom
CM-62578/expose-api-v4-cli-and-mcp
Apr 19, 2026
Merged

CM-62578: Expose Cycode API v4 through CLI commands#435
MaorDavidzon merged 1 commit intomainfrom
CM-62578/expose-api-v4-cli-and-mcp

Conversation

@MaorDavidzon
Copy link
Copy Markdown
Contributor

@MaorDavidzon MaorDavidzon commented Apr 12, 2026

Summary

  • Expose Cycode API v4 as CLI commands, dynamically generated from the OpenAPI spec
  • OpenAPI spec fetched from app.cycode.com and cached locally for 24h
  • All new commands marked as [EXPERIMENT]
  • Uses the CLI's standard auth client (same as scan/report commands)

Examples

Projects

cycode projects list --page-size 10 --query "Frontend"
cycode projects view 29303
cycode projects collisions --project-id 123
cycode projects collisions-count --project-id 123
cycode projects assets --project-id 123

Violations

cycode violations list --severity Critical --status Open --page-size 5
cycode violations list --category SAST --sort-by "-risk_score"
cycode violations view <violationId>
cycode violations count --severity High --category SecretDetection
cycode violations scan <scanId>

Workflows

cycode workflows list --query "classification"
cycode workflows view <workflowId>
cycode workflows count
cycode workflows jobs <workflowId>
cycode workflows jobs-count <workflowId>
cycode workflow-jobs list
cycode workflow-jobs view <jobId>

Members

cycode members list --page-size 5
cycode members view <memberId>
cycode members roles
cycode members me

Compliance

cycode frameworks list
cycode frameworks view <frameworkId>
cycode controls list --framework-id 1
cycode controls view <controlId>
cycode stats framework <frameworkId>
cycode stats posture

Audit logs

cycode audit-logs list --from 2024-01-01 --to 2024-12-31 --action Modified
cycode audit-logs view <id>

Scans & statistics

cycode scans list --page-size 5
cycode scans view <scanId>
cycode scans statistics --from 2024-01-01
cycode cli-scan-statistics scan-count --from 2024-01-01
cycode cli-scan-statistics top-cli-users --from 2024-01-01

Other resources

cycode labels list
cycode brokers list
cycode tokens tenant
cycode reports list
cycode secret-value-exclusions exclusions

Discovery

cycode --help                        # all 46 command groups
cycode violations --help             # subcommands for violations
cycode violations list --help        # all filter flags for listing violations

Architecture

  • OpenAPI spec fetched from app.cycode.com/v4/api-docs/cycode-api-swagger.json with a 3s timeout
  • If fetch times out, a background thread continues so the cache is warm for the next run
  • Cached runs have zero network overhead
  • Command names derived from URL path structure (not English summary parsing)
    • list for collections, view for single resources
    • Sub-paths become command names: /violations/countcount
  • Path parameters are URL-encoded to prevent path traversal
  • Auth uses CycodeTokenBasedClient (same as all other CLI commands)

Test plan

  • cycode projects list --page-size 2 returns project data
  • cycode violations list --severity Critical --status Open returns filtered violations
  • cycode projects view <ID> returns single project (path param)
  • cycode violations count --severity High returns count
  • cycode workflows list returns workflows
  • cycode members roles returns roles
  • cycode --help shows API command groups with [EXPERIMENT] label
  • All 645 existing tests pass
  • Graceful fallback when not authenticated (no API commands, no crash)
  • Spec caching works (second run has no fetch)
  • 3s timeout prevents blocking on slow networks

Jira: CM-62578

🤖 Generated with Claude Code

Comment thread poetry.lock Outdated
Comment thread poetry.lock Outdated
Comment thread poetry.lock Outdated
Comment thread poetry.lock Outdated
Comment thread poetry.lock Outdated
@MaorDavidzon MaorDavidzon changed the title CM-62578: Expose Cycode API v4 through CLI commands and MCP server CM-62578: Expose Cycode API v4 through CLI commands Apr 12, 2026
Copy link
Copy Markdown
Collaborator

@gotbadger gotbadger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should put all the commands under an api namespace so like cycode api violations right now its really cluttering up the main commands and means we can have naming collisions. This is similar to what github is doing for their CLI. Also if we do this it means when we run unrelated tasks we wont have pull the swagger file, we should try and do this as when CLI is run in CI/CD it will never be hitting cache.

Here is an example of where you get some annoying logging in a command due to the call for openAPI being made in the background.

poetry run cycode status                                                                                                       
[04/13/26 10:34:02] WARNING  [API Command] Could not load OpenAPI spec: Cycode credentials not found. Run `cycode auth` first, or set CYCODE_CLIENT_ID and CYCODE_CLIENT_SECRET environment variables.              api_command.py:128
Program: cycode
Version: 0.0.0
Os: Darwin
Arch: arm64
Python version: 3.13.7
Installation id: xxxx
App url: https://app.cycode.com
Api url: https://api.cycode.com
Is authenticated: False
User id: None
Tenant id: None
Supported modules:
  Secret scanning: False
  Sca scanning: False
  Iac scanning: False
  Sast scanning: False
  Ai large language model: False
....

Lastly we will need to add documentation to the Readme for these new commands. Having it under the api namespace will make this a bit easier I think in explaining generally what it does since its dynamic

@MaorDavidzon
Copy link
Copy Markdown
Contributor Author

MaorDavidzon commented Apr 13, 2026

@gotbadger Great feedback, thank you — all three points are valid.

You're right about the concrete issues:

  1. Top-level registration causes namespace collisions with curated commands (scan, auth, status, report)
  2. Spec is loaded on every invocation, including unrelated commands like cycode status — bad in CI where the cache is always cold
  3. The unauthenticated warning leaking into cycode status output is a real bug

On namespacing, going with platform instead of api:

I looked at how other CLIs handle this. gh api and glab api are raw URL passthroughs (gh api repos/owner/repo/issues) — what we built is structurally different: typed commands with proper args and --option flags generated from the spec. The closer analogs are aws <service>, gcloud <product>, az <group>, oci <service> — all of which put structured generated commands at the top level (because they bundle the spec).

Since we can't easily bundle the spec (it's tenant-aware and changes more frequently than CLI releases), namespacing is the right call. api telegraphs "raw escape hatch" the way gh api does, which doesn't match what these commands actually are. platform frames it as "the Cycode platform's full surface," reads naturally (cycode platform projects list), doesn't leak implementation detail (OpenAPI/spec/swagger), and ages better if we ever add POST/PUT.

Plan:

  • Move all generated commands under cycode platform <resource> <action>
  • Lazy-load the spec only when the user enters the platform group — no fetch on cycode scan, cycode status, etc.
  • Drop the startup warning entirely (only surface errors when the user is actually inside platform)
  • Add a README section explaining the platform namespace and how command discovery works

@MaorDavidzon MaorDavidzon requested a review from gotbadger April 13, 2026 13:46
Copy link
Copy Markdown
Collaborator

@gotbadger gotbadger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think we are mostly good structure wise here now, couple of things I spotted.

Comment thread cycode/cli/apps/api/openapi_spec.py
Comment thread cycode/cli/apps/api/__init__.py Outdated
Comment thread cycode/cli/apps/api/openapi_spec.py
@MaorDavidzon MaorDavidzon requested a review from gotbadger April 14, 2026 16:58
Add a new `cycode platform <resource> <action>` command namespace with
subcommands generated dynamically from the Cycode API v4 OpenAPI spec.

Key design decisions:
- Commands live under a `platform` namespace to avoid collisions with
  curated commands (scan, auth, status) and to signal "platform surface"
  rather than "raw API escape hatch"
- Spec is lazy-loaded: only fetched when the user enters `cycode platform`,
  so unrelated commands never trigger a network call or auth check
- Cached at ~/.cycode/openapi-spec.json for 24h with atomic writes
- Path-based command naming derived from URL structure (not summary parsing)
- Uses the CLI's standard auth client (CycodeTokenBasedClient)
- All commands marked [BETA]
- URL-encodes path params to prevent path traversal

New files:
- cycode/cli/apps/api/__init__.py — PlatformGroup (lazy Click group)
- cycode/cli/apps/api/api_command.py — OpenAPI-to-Click translator
- cycode/cli/apps/api/openapi_spec.py — spec fetch, cache, parse
- tests/cli/apps/api/ — 25 unit tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@MaorDavidzon MaorDavidzon force-pushed the CM-62578/expose-api-v4-cli-and-mcp branch from 2b5d1f0 to a616a1f Compare April 16, 2026 06:55
@MaorDavidzon MaorDavidzon merged commit e1f5eb7 into main Apr 19, 2026
28 checks passed
@MaorDavidzon MaorDavidzon deleted the CM-62578/expose-api-v4-cli-and-mcp branch April 19, 2026 07:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants